package simplescenegraph.math;

public class Matrix3f {
	
	public static final Matrix3f IDENTITY = new Matrix3f(1,0,0,0,1,0,0,0,1);
	
	public static final Matrix3f ZERO = new Matrix3f(0,0,0,0,0,0,0,0,0);
	
	public float[] m = new float[9];

	public Matrix3f() {
	}
	
	public Matrix3f(float m0, float m1, float m2, 
					float m3, float m4, float m5, 
					float m6, float m7, float m8) {
		m[0] = m0; m[1] = m1; m[2] = m2; 
		m[3] = m3; m[4] = m4; m[5] = m5;
		m[6] = m6; m[7] = m7; m[8] = m8;
	}
	
	public Matrix3f(Matrix3f arg0) {
		this(arg0.m[0], arg0.m[1], arg0.m[2],
		     arg0.m[3], arg0.m[4], arg0.m[5],
		     arg0.m[6], arg0.m[7], arg0.m[8]);
	}
	
	public void add(Matrix3f arg0) {
/*		for (int i = 0; i < 9; i++)
			m[i] += arg0.m[i];*/
		m[0] += arg0.m[0]; m[1] += arg0.m[1]; m[2] += arg0.m[2];
		m[3] += arg0.m[3]; m[4] += arg0.m[4]; m[5] += arg0.m[5];
		m[6] += arg0.m[6]; m[7] += arg0.m[7]; m[8] += arg0.m[8];		
	}
	
	public void subtract(Matrix3f arg0) {
/*		for (int i = 0; i < 9; i++)
			m[i] -= arg0.m[i];	*/
		m[0] -= arg0.m[0]; m[1] -= arg0.m[1]; m[2] -= arg0.m[2];
		m[3] -= arg0.m[3]; m[4] -= arg0.m[4]; m[5] -= arg0.m[5];
		m[6] -= arg0.m[6]; m[7] -= arg0.m[7]; m[8] -= arg0.m[8];		
	}
	
	public void multiply(float a) {
/*		for (int i = 0; i < 9; i++)
			m[i] *= a;*/
		m[0] *= a; m[1] *= a; m[2] *= a;
		m[3] *= a; m[4] *= a; m[5] *= a;
		m[6] *= a; m[7] *= a; m[8] *= a;	
	}
	
	public void multiply(Matrix3f arg0) {
		/*
		 * |a11b11 + a12b21 + a13b31		a11b12 + a12b22 + a13b32		a11b13 + a12b23 + a13b33|
		 * |a21b11 + a22b21 + a23b31		a21b12 + a22b22 + a23b32		a21b13 + a22b23 + a23b33|
		 * |a31b11 + a32b21 + a33b31		a31b12 + a32b22 + a33b32		a31b13 + a32b23 + a33b33|
		 */
		System.arraycopy(new float[] { 	m[0]*arg0.m[0] + m[1]*arg0.m[3] + m[2]*arg0.m[6], 	m[0]*arg0.m[1] + m[1]*arg0.m[4] + m[2]*arg0.m[7],	m[0]*arg0.m[2] + m[1]*arg0.m[5] + m[2]*arg0.m[8],
										m[3]*arg0.m[0] + m[4]*arg0.m[3] + m[5]*arg0.m[6],	m[3]*arg0.m[1] + m[4]*arg0.m[4] + m[5]*arg0.m[7],	m[3]*arg0.m[2] + m[4]*arg0.m[5] + m[5]*arg0.m[8],
										m[6]*arg0.m[0] + m[7]*arg0.m[3] + m[8]*arg0.m[6],	m[6]*arg0.m[1] + m[7]*arg0.m[4] + m[8]*arg0.m[7],	m[6]*arg0.m[2] + m[7]*arg0.m[5] + m[8]*arg0.m[8] }, 
							0, 
							m, 
							0, 
							9);
	}
	
	public void multiplyOther(Matrix3f arg0) {
		/*
		 * |a11b11 + a12b21 + a13b31		a11b12 + a12b22 + a13b32		a11b13 + a12b23 + a13b33|
		 * |a21b11 + a22b21 + a23b31		a21b12 + a22b22 + a23b32		a21b13 + a22b23 + a23b33|
		 * |a31b11 + a32b21 + a33b31		a31b12 + a32b22 + a33b32		a31b13 + a32b23 + a33b33|
		 */
		System.arraycopy(new float[] { 	m[0]*arg0.m[0] + m[1]*arg0.m[3] + m[2]*arg0.m[6], 	m[0]*arg0.m[1] + m[1]*arg0.m[4] + m[2]*arg0.m[7],	m[0]*arg0.m[2] + m[1]*arg0.m[5] + m[2]*arg0.m[8],
										m[3]*arg0.m[0] + m[4]*arg0.m[3] + m[5]*arg0.m[6],	m[3]*arg0.m[1] + m[4]*arg0.m[4] + m[5]*arg0.m[7],	m[3]*arg0.m[2] + m[4]*arg0.m[5] + m[5]*arg0.m[8],
										m[6]*arg0.m[0] + m[7]*arg0.m[3] + m[8]*arg0.m[6],	m[6]*arg0.m[1] + m[7]*arg0.m[4] + m[8]*arg0.m[7],	m[6]*arg0.m[2] + m[7]*arg0.m[5] + m[8]*arg0.m[8] }, 
							0, 
							arg0.m, 
							0, 
							9);		
	}
	
	public void multiplyOther(Vector3f arg0) {
		arg0.x = m[0]*arg0.x + m[1]*arg0.y + m[2]*arg0.z;
		arg0.y = m[3]*arg0.x + m[4]*arg0.y + m[5]*arg0.z;
		arg0.z = m[6]*arg0.x + m[7]*arg0.y + m[8]*arg0.z;
	}	
	
	public void divide(float a) {
/*		for (int i = 0; i < 9; i++)
			m[i] /= a;	*/
		m[0] /= a; m[1] /= a; m[2] /= a;
		m[3] /= a; m[4] /= a; m[5] /= a;
		m[6] /= a; m[7] /= a; m[8] /= a;
	}
	
	public float determinant() {
		/*	|a11	a12		a13|
		 * 	|a21	a22		a23| = a11(a22a33 - a23a32) - a12(a21a33 - a23a31) + a13(a21a32 - a22a31)
		 * 	|a31	a32		a33|
		 */
		return m[0]*(m[4]*m[8]-m[5]*m[7])-m[1]*(m[3]*m[8]-m[5]*m[6])+m[2]*(m[3]*m[7]-m[4]*m[6]);
	}
	
	public Matrix3f transpose() {
		/*
		 * |a11		a21		a31|
		 * |a12		a22		a32|	
		 * |a13		a23		a33|
		 */
		return new Matrix3f(m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]);
	}
	
	public Matrix3f inverse() {
		/*	|a22a33 - a23a32	a13a32 - a12a33		a12a23 - a13a22|
		 * 	|a23a31	- a21a33	a11a33 - a13a31		a13a21 - a11a23| * (1 / detA)
		 * 	|a21a32 - a22a31	a12a31 - a11a32		a11a22 - a12a21|
		 */
		Matrix3f r0 = new Matrix3f(m[4]*m[8] - m[5]*m[7], 		m[2]*m[7] - m[1]*m[8], 		m[1]*m[5] - m[2]*m[4],
			 					   m[5]*m[6] - m[3]*m[8], 		m[0]*m[8] - m[2]*m[6], 		m[2]*m[3] - m[0]*m[5],
			 					   m[3]*m[7] - m[4]*m[6], 		m[1]*m[6] - m[0]*m[7], 		m[0]*m[4] - m[1]*m[3]);
		r0.multiply(1 / determinant());
		return r0;
	}
	
	public void setIdentity() {
		m[0] = 1; m[1] = 0; m[2] = 0;
		m[3] = 0; m[4] = 1; m[5] = 0;
		m[6] = 0; m[7] = 0; m[8] = 1;
	}
	
	public Vector3f getColumn(int c) {
		return new Vector3f(m[c], m[c+3], m[c+6]);
	}
	
	public Vector3f getLine(int l) {
		return new Vector3f(m[l], m[l+1], m[l+2]);
	}
	
	public void setColumn(int c, Vector3f v0) {
		m[c] = v0.x; m[c+3] = v0.y; m[c+6] = v0.z;
	}
	
	public void setLine(int l, Vector3f v0) {
		m[l] = v0.x; m[l+1] = v0.y; m[l+2] = v0.z;
	}
	
	public float trace() {
		return m[0] + m[4] + m[8];
	}
	
	public boolean equals(Object obj0) {
		Matrix3f m0 = (Matrix3f) obj0;
		return 	m[0] == m0.m[0] && m[1] == m0.m[1] && m[2] == m0.m[2] &&
		 		m[3] == m0.m[3] && m[4] == m0.m[4] && m[5] == m0.m[5] &&
		 		m[6] == m0.m[6] && m[7] == m0.m[7] && m[8] == m0.m[8];		
	}
	
	public String toString() {
		return 	"|" + m[0] + '\t' + m[1] + '\t' + m[2] + "|\n" + 
				"|" + m[3] + '\t' + m[4] + '\t' + m[5] + "|\n" +
				"|" + m[6] + '\t' + m[7] + '\t' + m[8] + "|\n";
	}
	
}
